#!/usr/bin/env python
# -*- coding: utf-8 -*-

import time
import logging
import random
import string
import os
from datetime import datetime
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.action_chains import ActionChains
from selenium.common.exceptions import TimeoutException, NoSuchElementException

from tests.page_objects.base_page import BasePage

class BannerPage(BasePage):
    """轮播图管理页面对象"""
    
    # 导航菜单定位器
    CONTENT_MENU = (By.XPATH, "//span[text()='内容管理']")
    BANNER_MENU = (By.XPATH, "//li[contains(@class, 'el-menu-item')][.//text()='轮播图管理']")
    
    # 搜索表单定位器
    TITLE_INPUT = (By.XPATH, "//label[text()='标题']/following-sibling::div//input")
    STATUS_SELECT = (By.XPATH, "//label[text()='状态']/following-sibling::div//div[contains(@class, 'el-select')]")
    STATUS_SELECT_ALT = (By.CSS_SELECTOR, ".el-select__wrapper input[placeholder='选择状态']")
    SEARCH_BUTTON = (By.XPATH, "//button[contains(@class, 'el-button--primary')][.//span[text()='搜索']]")
    RESET_BUTTON = (By.XPATH, "//button[.//span[text()='重置']]")
    
    # 表格定位器
    BANNER_TABLE = (By.XPATH, "//table[contains(@class, 'el-table')]")
    TABLE_ROWS = (By.XPATH, "//table[contains(@class, 'el-table')]//tbody/tr")
    TABLE_LOADING = (By.XPATH, "//div[contains(@class, 'el-loading-mask')]")
    
    # 下拉选项定位器
    DROPDOWN_ITEM = (By.XPATH, "//div[contains(@class, 'el-select-dropdown') and not(contains(@style, 'display: none'))]//div[contains(@class, 'el-select-dropdown__item')]")
    
    # 新增轮播图按钮
    ADD_BANNER_BUTTON = (By.XPATH, "//button[contains(@class, 'el-button--primary')][.//span[text()='新增轮播图']]")
    
    # 轮播图对话框
    BANNER_DIALOG = (By.XPATH, "//div[contains(@class, 'el-dialog')][.//span[text()='新增轮播图']]")
    DIALOG_TITLE_INPUT = (By.XPATH, "//div[contains(@class, 'el-dialog')]//label[text()='标题']/following-sibling::div//input")
    DIALOG_LINK_INPUT = (By.XPATH, "//div[contains(@class, 'el-dialog')]//label[text()='链接']/following-sibling::div//input")
    DIALOG_SORT_INPUT = (By.XPATH, "//div[contains(@class, 'el-dialog')]//label[text()='排序']/following-sibling::div//input")
    DIALOG_STATUS_ENABLED = (By.XPATH, "//div[contains(@class, 'el-dialog')]//label[contains(@class, 'el-radio')][.//span[text()='启用']]")
    DIALOG_STATUS_DISABLED = (By.XPATH, "//div[contains(@class, 'el-dialog')]//label[contains(@class, 'el-radio')][.//span[text()='禁用']]")
    DIALOG_CONFIRM_BUTTON = (By.XPATH, "//div[contains(@class, 'el-dialog')]//button[contains(@class, 'el-button--primary')][.//span[text()='确定']]")
    DIALOG_CANCEL_BUTTON = (By.XPATH, "//div[contains(@class, 'el-dialog')]//button[.//span[text()='取消']]")
    
    # 图片上传区域
    IMAGE_UPLOAD_AREA = (By.XPATH, "//div[contains(@class, 'el-dialog')]//div[contains(@class, 'upload-placeholder')]")
    
    # 消息提示
    SUCCESS_MESSAGE = (By.CSS_SELECTOR, ".el-message--success")
    
    def __init__(self, driver):
        super().__init__(driver)
        self.actions = ActionChains(driver)
    
    def navigate_to_banner_page(self):
        """
        导航到轮播图管理页面
        """
        logging.info("导航到轮播图管理页面")
        
        try:
            # 等待内容管理菜单可见并点击
            try:
                content_menu = self.wait.until(EC.element_to_be_clickable(self.CONTENT_MENU))
                content_menu.click()
                logging.info("已点击内容管理菜单")
            except Exception as e:
                logging.warning(f"点击内容管理菜单失败: {e}")
                # 使用更通用的XPath
                try:
                    content_menu = self.wait.until(EC.element_to_be_clickable((By.XPATH, "//span[contains(text(), '内容管理')]")))
                    content_menu.click()
                    logging.info("已使用通用XPath点击内容管理菜单")
                except Exception as e2:
                    logging.warning(f"使用通用XPath点击内容管理菜单失败: {e2}")
                    # 使用JavaScript点击
                    self.driver.execute_script("""
                    var menuItems = document.querySelectorAll('span');
                    for (var i = 0; i < menuItems.length; i++) {
                        if (menuItems[i].textContent.includes('内容管理')) {
                            menuItems[i].click();
                            console.log('已通过JavaScript点击内容管理菜单');
                            break;
                        }
                    }
                    """)
            
            # 等待子菜单展开
            time.sleep(2)
            
            # 点击轮播图管理子菜单
            try:
                banner_menu = self.wait.until(EC.element_to_be_clickable(self.BANNER_MENU))
                banner_menu.click()
                logging.info("已点击轮播图管理子菜单")
            except Exception as e:
                logging.warning(f"点击轮播图管理子菜单失败: {e}")
                # 使用更通用的XPath
                try:
                    banner_menu = self.wait.until(EC.element_to_be_clickable((By.XPATH, "//li[contains(@class, 'el-menu-item')][contains(., '轮播图管理')]")))
                    banner_menu.click()
                    logging.info("已使用通用XPath点击轮播图管理子菜单")
                except Exception as e2:
                    logging.warning(f"使用通用XPath点击轮播图管理子菜单失败: {e2}")
                    # 使用JavaScript点击
                    self.driver.execute_script("""
                    var subMenuItems = document.querySelectorAll('li.el-menu-item');
                    for (var i = 0; i < subMenuItems.length; i++) {
                        if (subMenuItems[i].textContent.includes('轮播图管理')) {
                            subMenuItems[i].click();
                            console.log('已通过JavaScript点击轮播图管理子菜单');
                            break;
                        }
                    }
                    """)
            
            # 等待页面加载
            time.sleep(5)  # 增加等待时间
            
            try:
                self.wait.until(EC.presence_of_element_located(self.BANNER_TABLE))
                logging.info("轮播图管理页面已加载")
            except Exception as e:
                logging.warning(f"等待轮播图管理页面加载失败: {e}")
            
            # 截图
            self.take_screenshot("banner_page_loaded")
            
            return self
        except Exception as e:
            logging.error(f"导航到轮播图管理页面失败: {e}")
            self.take_screenshot("navigate_to_banner_page_failed")
            raise
    
    def search_banner(self, title=None, status=None):
        """
        搜索轮播图
        
        Args:
            title: 轮播图标题
            status: 轮播图状态 ('启用' 或 '禁用')
        """
        logging.info(f"搜索轮播图: 标题={title}, 状态={status}")
        
        try:
            # 输入标题
            if title:
                self.input_text(self.TITLE_INPUT, title)
                logging.info(f"已输入标题: {title}")
            
            # 选择状态
            if status:
                # 尝试多种方法点击状态下拉框
                try:
                    # 方法1: 使用主要定位器
                    logging.info("尝试点击状态下拉框")
                    self.click(self.STATUS_SELECT)
                except Exception as e1:
                    logging.warning(f"点击状态下拉框失败(方法1): {e1}")
                    try:
                        # 方法2: 使用备用CSS选择器
                        logging.info("尝试使用备用CSS选择器点击状态下拉框")
                        self.click(self.STATUS_SELECT_ALT)
                    except Exception as e2:
                        logging.warning(f"点击状态下拉框失败(方法2): {e2}")
                        try:
                            # 方法3: 使用JavaScript点击
                            logging.info("尝试使用JavaScript点击状态下拉框")
                            self.driver.execute_script("""
                            // 尝试通过placeholder找到元素
                            var statusInput = document.querySelector('input[placeholder="选择状态"]');
                            if (statusInput) {
                                statusInput.click();
                                console.log('已通过placeholder点击状态下拉框');
                                return;
                            }
                            
                            // 尝试通过label找到元素
                            var labels = document.querySelectorAll('label');
                            for (var i = 0; i < labels.length; i++) {
                                if (labels[i].textContent.includes('状态')) {
                                    var select = labels[i].nextElementSibling.querySelector('.el-select');
                                    if (select) {
                                        select.click();
                                        console.log('已通过label找到并点击状态下拉框');
                                        return;
                                    }
                                }
                            }
                            """)
                        except Exception as e3:
                            logging.warning(f"使用JavaScript点击状态下拉框失败: {e3}")
                
                # 等待下拉选项出现
                time.sleep(2)
                
                # 尝试选择对应状态
                try:
                    # 构建多种可能的选项定位器
                    status_options = [
                        (By.XPATH, f"//div[contains(@class, 'el-select-dropdown__item')][.//span[text()='{status}']]"),
                        (By.XPATH, f"//div[contains(@class, 'el-select-dropdown__item')][text()='{status}']"),
                        (By.XPATH, f"//div[contains(@class, 'el-select-dropdown__item')][contains(., '{status}')]")
                    ]
                    
                    # 尝试点击选项
                    clicked = False
                    for option in status_options:
                        try:
                            if self.is_element_present(option):
                                self.click(option)
                                logging.info(f"已选择状态: {status}")
                                clicked = True
                                break
                        except Exception as e:
                            logging.warning(f"点击状态选项失败: {e}")
                    
                    # 如果上述方法都失败，尝试使用JavaScript
                    if not clicked:
                        logging.info("尝试使用JavaScript选择状态")
                        self.driver.execute_script(f"""
                        var items = document.querySelectorAll('.el-select-dropdown__item');
                        for (var i = 0; i < items.length; i++) {{
                            if (items[i].textContent.includes('{status}')) {{
                                items[i].click();
                                console.log('已通过JavaScript选择状态: {status}');
                                break;
                            }}
                        }}
                        """)
                except Exception as e:
                    logging.warning(f"选择状态失败: {e}")
            
            # 点击搜索按钮
            try:
                self.click(self.SEARCH_BUTTON)
                logging.info("已点击搜索按钮")
            except Exception as e:
                logging.warning(f"点击搜索按钮失败: {e}")
                # 尝试使用JavaScript点击搜索按钮
                self.driver.execute_script("""
                var buttons = document.querySelectorAll('button');
                for (var i = 0; i < buttons.length; i++) {
                    if (buttons[i].textContent.includes('搜索')) {
                        buttons[i].click();
                        console.log('已通过JavaScript点击搜索按钮');
                        break;
                    }
                }
                """)
            
            # 等待搜索结果加载
            time.sleep(3)
            
            # 等待加载动画消失
            try:
                WebDriverWait(self.driver, 10).until_not(
                    EC.presence_of_element_located(self.TABLE_LOADING)
                )
            except:
                logging.warning("等待加载动画消失超时")
            
            # 截图
            self.take_screenshot("banner_search_results")
            
            return self
        except Exception as e:
            logging.error(f"搜索轮播图失败: {e}")
            self.take_screenshot("search_banner_failed")
            raise
    
    def reset_search(self):
        """
        重置搜索条件
        """
        logging.info("重置搜索条件")
        try:
            self.click(self.RESET_BUTTON)
            time.sleep(2)
            return self
        except Exception as e:
            logging.error(f"重置搜索失败: {e}")
            self.take_screenshot("reset_search_failed")
            raise
    
    def get_banner_count(self):
        """
        获取轮播图数量
        
        Returns:
            轮播图数量
        """
        try:
            rows = self.find_elements(self.TABLE_ROWS)
            count = len(rows)
            logging.info(f"轮播图数量: {count}")
            return count
        except Exception as e:
            logging.error(f"获取轮播图数量失败: {e}")
            return 0
    
    def is_banner_in_results(self, title=None):
        """
        检查指定标题的轮播图是否在搜索结果中
        
        Args:
            title: 轮播图标题
            
        Returns:
            布尔值，表示是否找到轮播图
        """
        if not title:
            return False
        
        try:
            # 构建标题单元格的XPath
            title_cell_xpath = f"//table[contains(@class, 'el-table')]//tbody/tr//td[2]//div[contains(text(), '{title}')]"
            
            # 检查是否存在匹配的标题
            found = self.is_element_present((By.XPATH, title_cell_xpath))
            
            if found:
                logging.info(f"找到标题为 '{title}' 的轮播图")
            else:
                logging.warning(f"未找到标题为 '{title}' 的轮播图")
            
            return found
        except Exception as e:
            logging.error(f"检查轮播图是否在结果中失败: {e}")
            return False
    
    def generate_random_banner_title(self, prefix="测试轮播图"):
        """
        生成随机轮播图标题，避免重名
        """
        timestamp = datetime.now().strftime("%m%d%H%M%S")
        random_str = ''.join(random.choices(string.ascii_lowercase + string.digits, k=3))
        return f"{prefix}_{timestamp}_{random_str}"
    
    def click_add_banner_button(self):
        """
        点击新增轮播图按钮
        """
        logging.info("点击新增轮播图按钮")
        
        try:
            # 尝试点击新增轮播图按钮
            try:
                add_button = self.wait.until(EC.element_to_be_clickable(self.ADD_BANNER_BUTTON))
                add_button.click()
                logging.info("已点击新增轮播图按钮")
            except Exception as e:
                logging.warning(f"点击新增轮播图按钮失败: {e}")
                
                # 尝试使用JavaScript点击
                try:
                    logging.info("尝试使用JavaScript点击新增轮播图按钮")
                    self.driver.execute_script("""
                    var buttons = document.querySelectorAll('button');
                    for (var i = 0; i < buttons.length; i++) {
                        if (buttons[i].textContent.includes('新增轮播图')) {
                            buttons[i].click();
                            console.log('已通过JavaScript点击新增轮播图按钮');
                            break;
                        }
                    }
                    """)
                except Exception as e2:
                    logging.error(f"使用JavaScript点击新增轮播图按钮失败: {e2}")
                    self.take_screenshot("click_add_banner_button_failed")
                    raise
            
            # 等待对话框显示
            self.wait.until(EC.visibility_of_element_located(self.BANNER_DIALOG))
            logging.info("新增轮播图对话框已显示")
            
            # 截图
            self.take_screenshot("add_banner_dialog_opened")
            
            return self
        except Exception as e:
            logging.error(f"点击新增轮播图按钮或等待对话框显示失败: {e}")
            self.take_screenshot("add_banner_dialog_failed")
            raise
    
    def fill_banner_form(self, title, link_url="/", sort=0, status="启用", skip_image=False, image_path=None):
        """
        填写轮播图表单
        
        Args:
            title: 轮播图标题
            link_url: 轮播图链接
            sort: 排序值
            status: 状态 ('启用' 或 '禁用')
            skip_image: 是否跳过图片上传
            image_path: 图片路径
        """
        logging.info(f"填写轮播图表单: 标题={title}, 链接={link_url}, 排序={sort}, 状态={status}")
        
        try:
            # 输入标题
            self.input_text(self.DIALOG_TITLE_INPUT, title)
            logging.info(f"已输入标题: {title}")
            
            # 输入链接
            self.input_text(self.DIALOG_LINK_INPUT, link_url)
            logging.info(f"已输入链接: {link_url}")
            
            # 输入排序
            # 先清空默认值
            sort_input = self.find_element(self.DIALOG_SORT_INPUT)
            sort_input.clear()
            # 输入新值
            sort_input.send_keys(str(sort))
            logging.info(f"已输入排序值: {sort}")
            
            # 选择状态
            if status == "启用":
                self.click(self.DIALOG_STATUS_ENABLED)
                logging.info("已选择状态: 启用")
            else:
                self.click(self.DIALOG_STATUS_DISABLED)
                logging.info("已选择状态: 禁用")
            
            # 处理图片上传
            if not skip_image:
                if image_path and os.path.exists(image_path):
                    try:
                        # 找到上传区域并点击
                        upload_area = self.find_element(self.IMAGE_UPLOAD_AREA)
                        
                        # 查找隐藏的文件输入框
                        file_input = self.driver.execute_script("""
                            var uploadArea = arguments[0];
                            var fileInput = uploadArea.querySelector('input[type="file"]');
                            if (!fileInput) {
                                // 如果找不到，尝试查找父元素中的文件输入框
                                fileInput = uploadArea.parentElement.querySelector('input[type="file"]');
                            }
                            return fileInput;
                        """, upload_area)
                        
                        if file_input:
                            # 设置文件路径
                            file_input.send_keys(image_path)
                            logging.info(f"已上传图片: {image_path}")
                            time.sleep(3)  # 等待上传完成
                        else:
                            logging.warning("未找到文件输入框，尝试使用JavaScript设置图片")
                            # 使用JavaScript直接设置imageUrl值，绕过上传
                            self.driver.execute_script("""
                            // 获取Vue实例并直接设置imageUrl
                            var app = document.querySelector('.banner-management').__vue__;
                            if (app && app.form) {
                                app.form.imageUrl = '/static/images/default-banner.jpg';
                                console.log('已通过JavaScript设置默认图片路径');
                            }
                            """)
                    except Exception as e:
                        logging.error(f"上传图片失败: {e}")
                        # 使用JavaScript直接设置imageUrl值，绕过上传
                        self.driver.execute_script("""
                        // 获取Vue实例并直接设置imageUrl
                        var app = document.querySelector('.banner-management').__vue__;
                        if (app && app.form) {
                            app.form.imageUrl = '/static/images/default-banner.jpg';
                            console.log('已通过JavaScript设置默认图片路径');
                        }
                        """)
                        logging.info("已尝试通过JavaScript设置默认图片路径")
                else:
                    logging.warning(f"图片路径不存在或未提供: {image_path}")
                    # 使用JavaScript直接设置imageUrl值，绕过上传
                    self.driver.execute_script("""
                    // 获取Vue实例并直接设置imageUrl
                    var app = document.querySelector('.banner-management').__vue__;
                    if (app && app.form) {
                        app.form.imageUrl = '/static/images/default-banner.jpg';
                        console.log('已通过JavaScript设置默认图片路径');
                    }
                    """)
                    logging.info("已尝试通过JavaScript设置默认图片路径")
            
            # 截图
            self.take_screenshot("banner_form_filled")
            
            return self
        except Exception as e:
            logging.error(f"填写轮播图表单失败: {e}")
            self.take_screenshot("fill_banner_form_failed")
            raise
    
    def submit_banner_form(self):
        """
        提交轮播图表单
        """
        logging.info("提交轮播图表单")
        
        try:
            # 点击确定按钮
            try:
                self.click(self.DIALOG_CONFIRM_BUTTON)
                logging.info("已点击确定按钮")
            except Exception as e:
                logging.warning(f"点击确定按钮失败: {e}")
                
                # 尝试使用JavaScript点击
                self.driver.execute_script("""
                var dialog = document.querySelector('.el-dialog');
                if (dialog) {
                    var buttons = dialog.querySelectorAll('button');
                    for (var i = 0; i < buttons.length; i++) {
                        if (buttons[i].textContent.includes('确定')) {
                            buttons[i].click();
                            console.log('已通过JavaScript点击确定按钮');
                            break;
                        }
                    }
                }
                """)
            
            # 等待对话框关闭
            try:
                WebDriverWait(self.driver, 10).until_not(
                    EC.visibility_of_element_located(self.BANNER_DIALOG)
                )
                logging.info("轮播图对话框已关闭")
            except TimeoutException:
                logging.warning("等待轮播图对话框关闭超时")
                
                # 尝试使用JavaScript关闭对话框
                try:
                    self.driver.execute_script("""
                    var confirmButton = document.querySelector('.dialog-footer .el-button--primary');
                    if (confirmButton) {
                        confirmButton.click();
                        console.log('已通过JavaScript点击确定按钮');
                    }
                    """)
                except Exception as e:
                    logging.error(f"使用JavaScript关闭对话框失败: {e}")
            
            # 等待成功消息显示
            try:
                self.wait.until(EC.visibility_of_element_located(self.SUCCESS_MESSAGE))
                logging.info("轮播图添加成功消息已显示")
                
                # 截图
                self.take_screenshot("add_banner_success")
            except TimeoutException:
                logging.warning("未检测到成功消息")
            
            return self
        except Exception as e:
            logging.error(f"提交轮播图表单失败: {e}")
            self.take_screenshot("submit_banner_form_failed")
            raise
    
    def cancel_banner_form(self):
        """
        取消轮播图表单
        """
        logging.info("取消轮播图表单")
        
        try:
            # 点击取消按钮
            self.click(self.DIALOG_CANCEL_BUTTON)
            
            # 等待对话框关闭
            WebDriverWait(self.driver, 10).until_not(
                EC.visibility_of_element_located(self.BANNER_DIALOG)
            )
            logging.info("轮播图对话框已关闭")
            
            return self
        except Exception as e:
            logging.error(f"取消轮播图表单失败: {e}")
            self.take_screenshot("cancel_banner_form_failed")
            raise
    
    def is_banner_added_successfully(self, title):
        """
        检查轮播图是否添加成功
        
        Args:
            title: 轮播图标题
            
        Returns:
            布尔值，表示轮播图是否添加成功
        """
        try:
            # 检查成功消息
            success_message = self.is_element_present(self.SUCCESS_MESSAGE)
            
            if success_message:
                message = self.get_text(self.SUCCESS_MESSAGE)
                logging.info(f"检测到成功消息: {message}")
            else:
                logging.warning("未检测到成功消息")
            
            # 搜索新添加的轮播图
            self.search_banner(title=title)
            
            # 检查搜索结果
            found = self.is_banner_in_results(title=title)
            
            return found and success_message
        except Exception as e:
            logging.error(f"检查轮播图是否添加成功时出错: {e}")
            return False 